package se.webbzon.boltzmann.game.event;

import java.util.Collection;

import se.webbzon.boltzmann.camera.AbstractCamera;
import se.webbzon.boltzmann.camera.Camera;
import se.webbzon.boltzmann.environment.AbstractEnvironment;
import se.webbzon.boltzmann.environment.PlayerEnvironment;
import se.webbzon.boltzmann.game.object.camera.GameCamera;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.sequence.Sequence;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceBinding;
import se.webbzon.boltzmann.player.Player;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldView;
import se.webbzon.oschi01.worldobject.WorldObject;

public class ResetCameraEvent extends AbstractGameEvent {
	
	// Whatever all cameras should be set
	private final boolean all;
		
	// The sequence of associated with this event
	private final Sequence sequence;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public ResetCameraEvent(Sequence sequence, boolean all) {
		this.sequence = sequence;
		this.all = all;
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override protected void onBegin(WorldArea world) {
		Collection<AbstractCamera> allCameras = world.findInstances(AbstractCamera.class);
		Collection<GameCamera> gameCameras = world.findInstances(GameCamera.class);
		if (all) 
			resetAll(allCameras,gameCameras);
		else
			resetSingle(allCameras,gameCameras);
		end();
	}

	@Override protected void onEnd() {
		
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Sets the camera for the player associated with the
	 *  sequence of this event. **/
	private final void resetSingle(Collection<AbstractCamera> allCameras, Collection<GameCamera> gameCameras) {
		WorldObject wo = sequence.getBinding(AbstractSequenceBinding.PLAYER);
		if (wo instanceof AbstractPlayerCharacter) {
			Player player = ((AbstractPlayerCharacter) wo).getPlayer();
			WorldView view = player.getView();
			for (Camera c : allCameras)
				c.removeView(view);
			for (GameCamera c : gameCameras) {
				if (c.getPlayer() == player) {
					c.addView(view);
					break;
				}
			}
		}
	}
	
	/** Resets the camera for all the players. **/
	private final void resetAll(Collection<AbstractCamera> allCameras, Collection<GameCamera> gameCameras) {
		AbstractEnvironment env = sequence.getEnvironment();
		if (env instanceof PlayerEnvironment) {
			for (Camera c : allCameras)
				c.clearViews();
			Collection<Player> players = ((PlayerEnvironment) env).getPlayers();
			synchronized (players) {
				for (Player player : players) {
					for (GameCamera c : gameCameras) {
						if (c.getPlayer() == player)
							c.addView(player.getView());
					}
				}
			}
		}
	}

}
